#include <Utility/helper.hpp>

namespace occ {
	inline void faceFragmentShader(
		IN vec3f& tri_center,
		IN vec3f& tri_normal,
		IN vec3f& light_pos,
		IN Color& light_color,
		IN Color& face_color,
		OUT Color& color)
	{
		// ambient
		occFloat ambientStrength = 0.1;
		vec3f result = ambientStrength * vec3f(light_color) * vec3f(face_color) / occFloat(255.0);

		// diffuse
		vec3f light_dir = glm::normalize(light_pos - tri_center);
		occFloat diff = fmax(glm::dot(tri_normal, light_dir), (occFloat)0.0);
		//occFloat diff = abs(glm::dot(tri_normal, light_dir));
		result += vec3f(face_color) * vec3f(light_color) * diff / occFloat(255.0);

		result.r = clamp(floor(result.r), occFloat(0), occFloat(255));
		result.g = clamp(floor(result.g), occFloat(0), occFloat(255));
		result.b = clamp(floor(result.b), occFloat(0), occFloat(255));

		color.r = unsigned char(result.r);
		color.g = unsigned char(result.g);
		color.b = unsigned char(result.b);
		color.w = 255;
	}

	inline void facePhongFragmentShader(
		IN vec3f& tri_center,
		IN vec3f& tri_normal,
		IN vec3f& light_pos,
		IN Color& light_color,
		IN Color& face_color,
		OUT Color& color)
	{
		// ambient
		occFloat ambientStrength = 0.1;
		vec3f result = ambientStrength * vec3f(light_color) * vec3f(face_color) / occFloat(255.0);

		// diffuse
		vec3f light_dir = glm::normalize(light_pos - tri_center);
		occFloat diff = fmax(glm::dot(tri_normal, light_dir), (occFloat)0.0);
		result += vec3f(face_color) * vec3f(light_color) * diff / occFloat(255.0);

		// specular
		occFloat specularStrength = 0.5;
		vec3f view_dir = glm::normalize(tri_center);
		vec3f reflect_dir = glm::reflect(-light_dir, tri_normal);
		occFloat spec = pow(fmax(glm::dot(-view_dir, reflect_dir), 0.0), 32);
		result += vec3f(light_color) * specularStrength * spec;

		result.r = clamp(floor(result.r), occFloat(0), occFloat(255));
		result.g = clamp(floor(result.g), occFloat(0), occFloat(255));
		result.b = clamp(floor(result.b), occFloat(0), occFloat(255));

		color.r = unsigned char(result.r);
		color.g = unsigned char(result.g);
		color.b = unsigned char(result.b);
		color.w = 255;
	}
}